/**
 * 
 */
package com.hanhai.zrb.api.biz.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.hanhai.zrb.api.biz.dao.mybatis.CommonCounterMapper;
import com.hanhai.zrb.api.biz.service.CommonCounterService;
import com.hanhai.zrb.model.common.CommonCounter;
import com.hanhai.zrb.model.common.CommonCounterKey;
import com.hanhai.zrb.model.common.CommonCounterKey.MainKeyType;

/**
 * @author leiruiqi
 *
 */
@Service("commonCounterService")
public class CommonCounterServiceImpl implements CommonCounterService{

	@Resource
	private CommonCounterMapper commonCounterMapper;
	
	@Override
	public boolean create(CommonCounter record) {
		boolean bool = checkKeyAvailable(record.getMainKey(),record.getSecondaryKey());
		if(bool == false){
			throw new RuntimeException();
		}
		try {
			commonCounterMapper.insert(record);
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	
	@Override
	public boolean addOne(CommonCounterKey commonCounterKey) {
		
		if(0==commonCounterMapper.addOne(commonCounterKey.getMainKey(), commonCounterKey.getSecondaryKey())){
			CommonCounter commonCounter = new CommonCounter();
			commonCounter.setMainKey(commonCounterKey.getMainKey());
			commonCounter.setSecondaryKey(commonCounterKey.getSecondaryKey());
			commonCounter.setValue(0L);
			this.create(commonCounter);
		}else{
			return true;
		}
		return 1==commonCounterMapper.addOne(commonCounterKey.getMainKey(), commonCounterKey.getSecondaryKey());
	}

	@Override
	public boolean addOneForMaxValue(CommonCounterKey commonCounterKey,
			Long maxValue) {
		return 1==commonCounterMapper.addOneForMaxValue(commonCounterKey.getMainKey(), commonCounterKey.getSecondaryKey(), maxValue);
	}

	@Override
	public boolean subOne(CommonCounterKey commonCounterKey) {
		return 1==commonCounterMapper.subOne(commonCounterKey.getMainKey(), commonCounterKey.getSecondaryKey());
	}

	@Transactional
	@Override
	public boolean addOneByLock(CommonCounterKey commonCounterKey) {
		CommonCounter commonCounter = selectForLock(commonCounterKey);
		if(commonCounter!=null){
			return 1==commonCounterMapper.addOne(commonCounterKey.getMainKey(), commonCounterKey.getSecondaryKey());
		}
		return false;
	}


	@Transactional
	@Override
	public boolean addOneForMaxValueByLock(CommonCounterKey commonCounterKey,
			Long maxValue) {
		CommonCounter commonCounter = selectForLock(commonCounterKey);
		if(commonCounter!=null){
			return 1==commonCounterMapper.addOneForMaxValue(commonCounterKey.getMainKey(), commonCounterKey.getSecondaryKey(),maxValue);
		}
		return false;
	}

	@Transactional
	@Override
	public boolean subOneByLock(CommonCounterKey commonCounterKey) {
		
		CommonCounter commonCounter = selectForLock(commonCounterKey);
		if(commonCounter!=null){
			return 1==commonCounterMapper.subOne(commonCounterKey.getMainKey(), commonCounterKey.getSecondaryKey());
		}
		return false;
	}


	
	@Transactional(propagation = Propagation.MANDATORY)
	@Override
	public CommonCounter selectForLock(CommonCounterKey commonCounterKey) {
		CommonCounter commonCounter = commonCounterMapper.selectForUpdate(commonCounterKey.getMainKey(), commonCounterKey.getSecondaryKey());
		if(commonCounter==null){
			commonCounter = new CommonCounter();
			commonCounter.setMainKey(commonCounterKey.getMainKey());
			commonCounter.setSecondaryKey(commonCounterKey.getSecondaryKey());
			commonCounter.setValue(0L);
			this.create(commonCounter);
			commonCounter = commonCounterMapper.selectForUpdate(commonCounterKey.getMainKey(), commonCounterKey.getSecondaryKey());
		}
		return commonCounter;
	}


	@Override
	public boolean exist(CommonCounterKey commonCounterKey) {
		CommonCounter commonCounter = commonCounterMapper.getByKey(commonCounterKey.getMainKey(), commonCounterKey.getSecondaryKey());
		return commonCounter!=null;
	}
	
	@Override
	public Long getCurrentCountByKey(CommonCounterKey commonCounterKey) {
		CommonCounter commonCounter = commonCounterMapper.getByKey(commonCounterKey.getMainKey(), commonCounterKey.getSecondaryKey());
		if(commonCounter==null){
			return 0L;
		}
		return commonCounter.getValue();
	}
	
	@Override
	public List<CommonCounter> getListByKeyList(
			List<CommonCounterKey> commonCounterKeyList) {
		return commonCounterMapper.getListBykeyList(commonCounterKeyList);
	}



	
	private boolean checkKeyAvailable(CommonCounterKey commonCounterKey){
		return checkKeyAvailable(commonCounterKey.getMainKey(),commonCounterKey.getSecondaryKey());
	}
	private boolean checkKeyAvailable(String mainKey,String secondaryKey){
		if(StringUtils.isBlank(mainKey)||StringUtils.isBlank(secondaryKey)){
			return false;
		}
		return true;
	}


	@Override
	public boolean update(CommonCounter record) {
		CommonCounter commonCounter = selectForLock(record);
		if(commonCounter!=null){
			return 1==commonCounterMapper.update(record);
		}
		return false;
	}


	@Override
	public Map<Long,Long> getListByMainKey(String mainKey) {
		Map<Long,Long> map = new HashMap();
		List<CommonCounter> list = commonCounterMapper.getListByMainKey(mainKey);
		if(CollectionUtils.isNotEmpty(list)){
			for(CommonCounter counter:list){
				map.put(Long.valueOf(counter.getSecondaryKey()), counter.getValue());
			}
		}
		return map;
	}


	@Override
	public List<CommonCounter> getListBySecondekeyList(
			CommonCounterKey commonCounterKey) {
		List<CommonCounter> list = commonCounterMapper.getListBySecondekeyList(commonCounterKey.getMainKey(), commonCounterKey.getSecondaryKeyList());
		return list;
	}


	@Override
	public Map<String,CommonCounter> listMapBySecondaryKeyList(String mainKeyType,List<String> secondaryKeyList) {
		Map<String,CommonCounter> map = new HashMap<String,CommonCounter>();
		List<CommonCounter> list = commonCounterMapper.getListBySecondekeyList(mainKeyType,secondaryKeyList);
		for(CommonCounter counter:list){
			map.put(counter.getMainKey(), counter);
		}
		return map;
	}
	
	@Override
	public Map<String,Long> listCountMapBySecondaryKeyList(String mainKeyType,List<String> secondaryKeyList) {
		Map<String,Long> map = new HashMap<String,Long>();
		if(CollectionUtils.isEmpty(secondaryKeyList)){
			return map;
		}
		List<CommonCounter> list = commonCounterMapper.getListBySecondekeyList(mainKeyType,secondaryKeyList);
		for(CommonCounter counter:list){
			map.put(counter.getMainKey(), counter.getValue());
		}
		return map;
	}
	

}
